package com.tian.controller;


import com.tian.pojo.Users;
import com.tian.pojo.bo.ShopcartBO;
import com.tian.pojo.bo.UserBO;
import com.tian.pojo.vo.UsersVO;
import com.tian.service.UserService;
import com.tian.utils.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Api(value = "注册登录",tags = "用于注册登录的相关接口")
@RestController
@RequestMapping("passport")
public class PassportController extends BaseController{
    @Autowired
    private UserService userService;

    @Autowired
    private RedisOperator redisOperator;

    @ApiOperation(value = "用户名是否存在",notes = "用户名是否存在",httpMethod = "GET")
    @GetMapping("/usernameIsExist")
    public JSONResult usernameIsExist(@RequestParam String username){
        //1.判断用户名不能为空
        if (StringUtils.isBlank(username)){
            return JSONResult.errorMsg("用户名不能为空");
        }
        //2.查找注册的用户名是否存在
        boolean isExist = userService.queryUsernameIsExist(username);
        if (isExist){
            return JSONResult.errorMsg("用户名已经存在");
        }
        //3.请求成功，用户名没有重复
        return JSONResult.ok();
    }


    @ApiOperation(value = "用户注册",notes = "用户注册",httpMethod = "POST")
    @PostMapping("/regist")
    public JSONResult regist(@RequestBody UserBO userBO,HttpServletRequest request,HttpServletResponse response){
        String username = userBO.getUsername();
        String password = userBO.getPassword();
        String confirmPassword = userBO.getConfirmPassword();

        //0.判断用户名和密码是否为空
        if (StringUtils.isBlank(username)||StringUtils.isBlank(password)||StringUtils.isBlank(confirmPassword)){
            return JSONResult.errorMsg("用户名或密码不能为空");
        }
        //1.查询用户名是否存在
        boolean isExist = userService.queryUsernameIsExist(username);
        if (isExist){
            return JSONResult.errorMsg("用户名已经存在");
        }
        //2.密码长度不能少于6位
        if (password.length()<6){
            return JSONResult.errorMsg("密码长度不能少于6位");
        }

        //3.判断两次密码是否一致
        if (!password.equals(confirmPassword)){
            return JSONResult.errorMsg("两次密码输入的不一致");
        }

        //4.实现注册
        Users user = userService.createUser(userBO);

        //因为用了usersVO，所以setNUllProperties方法就不用了
       // user = setNullProperties(user);

        //实现用户的redis会话
        UsersVO usersVO = conventUsersVO(user);

        CookieUtils.setCookie(request,response,"user", JsonUtils.objectToJson(usersVO),true);


        //同步购物车数据
        synchShopcartData(user.getId(),request,response);

        return JSONResult.ok();
    }

    public UsersVO conventUsersVO(Users user){
        //实现用户的redis会话
        String uniqueToken= UUID.randomUUID().toString().trim();
        redisOperator.set(REDIS_USER_TOKEN+":"+user.getId(),uniqueToken);
        UsersVO usersVO=new UsersVO();
        BeanUtils.copyProperties(user,usersVO);
        usersVO.setUserUniqueToken(uniqueToken);
        return usersVO;

    }

    @ApiOperation(value = "用户登录",notes = "用户登录",httpMethod = "POST")
    @PostMapping("/login")
    public JSONResult login(@RequestBody UserBO userBO, HttpServletRequest request, HttpServletResponse response) throws Exception{
        String username= userBO.getUsername();
        String password=userBO.getPassword();

        if (StringUtils.isBlank(username)||StringUtils.isBlank(password)){
            return JSONResult.errorMsg("用户名或密码不能为空");
        }

        Users user = userService.queryUserForLogin(username, MD5Utils.getMD5Str(password));


        if (user==null){
            return JSONResult.errorMsg("用户名或密码不正确");
        }

        // user = setNullProperties(user);

        //实现用户的redis会话
        UsersVO usersVO = conventUsersVO(user);

        CookieUtils.setCookie(request,response,"user", JsonUtils.objectToJson(usersVO),true);


        //同步购物车数据
        synchShopcartData(user.getId(),request,response);

        return JSONResult.ok(user);
    }

    /**
     * 注册登录成功后，同步cookie和redis中的购物车数据
     */
    private void synchShopcartData(String userId,HttpServletRequest request,HttpServletResponse response){
        /**
         * 1.redis中无数据，如果cookie中的购物车为空，那么这个时候不做任何处理；
         *                如果cookie中的购物车不为空，此时直接放入reids中
         *
         * 2.redis中有数据，如果cookie中的购物车为空，那么直接把redis的购物车覆盖本地
         *                如果cookie中的购物车不为空，
         *                     如果cookie中的某个商品在redis中存在，
         *                     则以cookie为主，删除redis中的，
         *                     把cookie中的商品直接覆盖redis中。
         * 3.同步到redis中去了以后，覆盖本地cookie购物车的数据，保证本地购物车的数据是同步最新的
         *
         */

        //从redis中获取购物车
        String shopcartJsonRedis=redisOperator.get(FOODIE_SHOPCART+":"+userId);
        //从cookie中获取购物车
        String shopcartStrCookie=CookieUtils.getCookieValue(request,FOODIE_SHOPCART,true);

        if (StringUtils.isBlank(shopcartJsonRedis)){
            //redis为空，cookie不为空，直接把cookie中的数据放入redis
            if (StringUtils.isNotBlank(shopcartStrCookie)){
                redisOperator.set(FOODIE_SHOPCART+":"+userId,shopcartStrCookie);
            }
        }else {
            //redis不为空，cookie不为空，合并cookie和redis中的购物车的商品数据（同一商品则覆盖redis）
            if (StringUtils.isNotBlank(shopcartStrCookie)){

                /**
                 * 1.已经存在的，把cookie中对应的数量，覆盖redis
                 * 2.该项商品标记为待删除，统一放入一个待删除的list
                 * 3.从cookie中清理所有的待删除list
                 * 4.合并redis和cookie中的数据
                 * 5.更新redis和cookie
                 */
                List<ShopcartBO> shopcartListRedis = JsonUtils.jsonToList(shopcartJsonRedis, ShopcartBO.class);
                List<ShopcartBO> shopcartListCookie = JsonUtils.jsonToList(shopcartStrCookie, ShopcartBO.class);

                //定义一个待删除的list
                List<ShopcartBO> pendingDeleteList=new ArrayList<>();

                for (ShopcartBO redisShopcart:shopcartListRedis){
                    String redisSpecId=redisShopcart.getSpecId();

                    for (ShopcartBO cookieShopcart:shopcartListCookie){
                        String cookieSpecId = cookieShopcart.getSpecId();

                        if (redisSpecId.equals(cookieSpecId)){
                            //覆盖购买数量，不累加，参考京东
                            redisShopcart.setBuyCounts(cookieShopcart.getBuyCounts());
                            //把cookieShopcart放入待删除列表，用于最后的删除与合并
                            pendingDeleteList.add(cookieShopcart);
                        }
                    }
                }
                //从现有cookie中删除对应的覆盖过的商品数据
                shopcartListCookie.removeAll(pendingDeleteList);

                //合并两个list
                shopcartListRedis.addAll(shopcartListCookie);
                //更新到redis和cookie中
                CookieUtils.setCookie(request,response,FOODIE_SHOPCART,JsonUtils.objectToJson(shopcartListRedis),true);
                redisOperator.set(FOODIE_SHOPCART+":"+userId,JsonUtils.objectToJson(shopcartListRedis));


            }else {
                //redis不为空，cookie为空，直接把redis覆盖cookie
                CookieUtils.setCookie(request,response,FOODIE_SHOPCART,shopcartJsonRedis,true);
            }
        }
    }

    private Users setNullProperties(Users user){
        user.setPassword(null);
        user.setMobile(null);
        user.setEmail(null);
        user.setUpdatedTime(null);
        user.setCreatedTime(null);
        user.setBirthday(null);
        return user;
    }

    @ApiOperation(value = "用户退出登录",notes = "用户退出登录",httpMethod = "POST")
    @PostMapping("/logout")
    public JSONResult logout(@RequestParam String userId,
                            HttpServletRequest request,
                            HttpServletResponse response){

        //清除用户的相关信息的cookie
        CookieUtils.deleteCookie(request,response,"user");

        //  用户退出登录,清除redis的user会话信息
        redisOperator.del(REDIS_USER_TOKEN+":"+userId);

        //分布式会话中需要清除用户数据
        CookieUtils.deleteCookie(request,response,FOODIE_SHOPCART);

        return JSONResult.ok();
    }
}
